package cn.e2win.biz.base;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Table;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import cn.e2win.base.controller.MyException;
import cn.e2win.base.entity.BaseApproveI;
import cn.e2win.base.entity.BaseEntity;
import cn.e2win.base.entity.SysApproveLog;
import cn.e2win.base.entity.SysAttach;
import cn.e2win.base.entity.SysLogs;
import cn.e2win.base.entity.SysUser;
import cn.e2win.biz.dbo.Notice;
import cn.e2win.biz.security.UserSession;
import cn.e2win.biz.util.GenericsUtils;
import cn.e2win.biz.util.StringUtils;


public abstract class BaseService implements InitializingBean{
	static Log LOGGER = LogFactory.getLog(BaseService.class);
	private BaseDAO dao;	
	public static String TODAY="";
	public static int    TODAY_CNT=0;

	public abstract BaseDAO  initDao();
	
	@Override
	public void afterPropertiesSet() throws Exception {
		this.dao = this.initDao();
	}
	 

	@Transactional
	public void delEntity(Class clazz, Integer id) {

			Object obj= dao.getEntity(clazz,id);
			if(obj instanceof BaseEntity ){
				((BaseEntity)obj).setActiveStatusInt(0);
				obj = dao.merge(obj);
				

				SysLogs logs = new SysLogs(obj, SysLogs.DEL);
				if(logs.getOperatorType()!=null){
					setCurrentUserInfo(logs);
					dao.merge(logs);
				}
			}else{
				dao.delete(obj);
			}

	}
	public Map<String, Object> getMapEntity(Class clazz, Serializable id){
		Map<String, Object> rMap = new HashMap<String, Object>();
		Table annotation = (Table)clazz.getAnnotation(Table.class);
        if(annotation != null){
    		SysUser user = UserSession.getUser();
    		String sql = annotation.name();
        	sql = "SELECT * FROM " + sql + " WHERE id=" + id;
            System.err.println(sql);
        	rMap = dao.get1stRecordBySql(sql, new HashMap<String,Object>());
			System.err.println("=====在此处进行数据安全判断!");
        	if(rMap!=null && rMap.get("coId")!=null && !rMap.get("coId").equals(user.getCoId())){
        		rMap = new HashMap<String, Object>();
        	}
        }
		return rMap;
	}
	public Object getEntity(Class clazz, Serializable id){
		SysUser user = UserSession.getUser();
		Object obj = dao.getEntity(clazz, id);
		/*if(obj instanceof BaseEntity){
			System.err.println("=====在此处进行数据安全判断!");
			BaseEntity bO=(BaseEntity)obj;
			if(bO.getCoId()==null || bO.getCoId().equals(user.getCoId()) || user.getCoId()==-99){//-99为微信上的操作
				
			}else{
				obj=null;
			}
		}*/
		return obj;		
	}

	public Map<String, Object> getEntity(BaseEntity entity){
		return dao.getEntity(entity);
	}
	@Transactional
	public void saveAll(List<?>  list) {
		this.dao.saveAll(list);
	}
	/*
	public Object edit(Object o){
		return dao.merge(o);
	}
*/



	/**
	 * @param o
	 * @throws MyException
	 * 记录审核日志及发送审核消息
	 */
	@Transactional
	private void processApprove(BaseApproveI o)  throws MyException{
		if(!StringUtils.isEmpty(o.getApproveStatus())){
			SysApproveLog approveLog = new SysApproveLog(o);
			edit(approveLog);
			Notice notice = o.getApproveNotice();
			if(notice!=null){
				edit(notice);
			}
		}
	}
	@Transactional
	public Object edit(Object o)  throws MyException{
		/**
		 * 
		 * 这里需要用反射来判断
		 * 先从DB读取一个,找到ID,再读一个
		 * 再判断页面传过偶来的字段是否为空,为空就不更新
		 * 为空字符串的字段需要更新(比如需要清空一个属性的时候)
		 */
		try {
			Object returnObj = null;
			String oldApvStatus = null;
			Object id = GenericsUtils.getPKValue(o);

			String operatorType = null;
			if(id!=null){
				Object objOld = dao.getEntity(o.getClass(),(Serializable)id);
				if(objOld!=null){

					if(objOld instanceof BaseApproveI){
						oldApvStatus = ((BaseApproveI)objOld).getApproveStatus()+"";
					}
					
					GenericsUtils.setFieldValue(o, objOld);
					setCurrentUserInfo(objOld);
					returnObj = dao.merge(objOld);
				}else{
					id=null;
				}
				
			}else if(id==null){
				operatorType = SysLogs.NEW;
				setCurrentUserInfo(o);
				returnObj = dao.merge(o);
			}
			

			if(returnObj instanceof BaseEntity){
				SysLogs logs = ((BaseEntity)returnObj).getSysLogs();
				if(logs!=null){					
					logs.setEntityType(returnObj.getClass().getSimpleName());
					logs.setEntityId(((BaseEntity)returnObj).getId());	
					logs.setEntityNo(((BaseEntity)returnObj).getNo());
					if(operatorType!=null){
						logs.setOperatorType(operatorType);
					}
					setCurrentUserInfo(logs);
					dao.merge(logs);
				}
			}
			//可审核对象
			if(returnObj instanceof BaseApproveI){
				BaseApproveI tempO = (BaseApproveI)o;
				BaseApproveI rtnApv = (BaseApproveI)returnObj;
				
				rtnApv.setApproveDesc(tempO.getApproveDesc());
				//状态发生变化
				if((rtnApv.getApproveStatus()!=null && !rtnApv.getApproveStatus().equals(oldApvStatus))){//第一次保存
					processApprove(rtnApv);
				}
			}
			return returnObj;
			
		} catch (Exception e) {
			//logger.error(e);
			throw new MyException("update failed!", e);
			
		}
		
	}
	
	
/*
	@Transactional
	public Object edit(Object o, SysLogs logs) throws MyException{
		o = edit(o);
		logs.setEntityType(o.getClass().getSimpleName());
		if(o instanceof BaseEntity){
			logs.setEntityId(((BaseEntity)o).getId());	
			logs.setEntityNo(((BaseEntity)o).getNo());
		}
		return o;
		
	}
*/

	private Method getMethod(Object object, String methodName, Class clazz){
		Method method = null;
		try{
			method = object.getClass().getSuperclass().getDeclaredMethod(methodName, clazz);
		}catch (NoSuchMethodException e1) {
			try{
				method = object.getClass().getSuperclass().getSuperclass().getDeclaredMethod(methodName, clazz);
			}catch (NoSuchMethodException e2) {
				try{
					method = object.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredMethod(methodName, clazz);
				}catch (NoSuchMethodException e3) {
					
				}
			}
		}
		return method;
	}

	private Method getMethod(Object object, String methodName){
		Method method = null;
		try{
			method = object.getClass().getSuperclass().getDeclaredMethod(methodName);
		}catch (NoSuchMethodException e1) {
			try{
				method = object.getClass().getSuperclass().getSuperclass().getDeclaredMethod(methodName);
			}catch (NoSuchMethodException e2) {
				try{
					method = object.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredMethod(methodName);
				}catch (NoSuchMethodException e3) {
					
				}
			}
		}
		return method;
	}
	public void setCurrentUserInfo(Object object){
		SysUser user = UserSession.getUser();
		try {
			Method getId = getMethod(object, "getId");
			Object id = getId.invoke(object);

			String setDateMethod = "setUpdateDate";
			String setUserMethod= "setUpdateById";
			if(id==null){
				setDateMethod = "setCreateDate";
				setUserMethod= "setCreateById";

				Method setCoid = getMethod(object, "setCoId", Integer.class);
				if(setCoid != null){
					setCoid.invoke(object, user.getCoId());
				}
			}

/*			Method setActiveStatus = getMethod(object, "setActiveStatusInt", Integer.class);
			setActiveStatus.invoke(object, 1);*/
			
			Method setDate = getMethod(object, setDateMethod, Timestamp.class);
			setDate.invoke(object, new Timestamp(new Date().getTime()));
			if (null == user) {
				return;
			}
			Method setUser = getMethod(object, setUserMethod, Integer.class);
			setUser.invoke(object, user.getId());
			
		} catch (Exception e) {
			e.printStackTrace();
			LOGGER.error(e);
		}
	}
	
	/*
	public synchronized void sendMsg(BaseEntity obj){
		SysCompany company = (SysCompany)this.getEntity(SysCompany.class,obj.getCoId());
		
		ArrayList<MsgLogs> msgList = new ArrayList<MsgLogs>();
		if(obj instanceof Order){
			Order order  = (Order)obj;
			if(company.getMsgSenderInt()>0){
				MsgLogs smsMsg = new MsgLogs(order, "SMS");
				msgList.add(smsMsg);
			}
			msgList.add(new MsgLogs(order,"WeiXin"));
		}
		
		String status = "";
		for(MsgLogs msgLogs: msgList){
			if(company.getSmsQty()>0){
				SmsSender send = new SmsSender(this, msgLogs);
				send.sendNow();
			}else{
				status = "-3";//短信数量不足
			}
			if(StringUtils.isNumeric(status)){
				int qty = Integer.parseInt(status);
				if(qty>0){
					msgLogs.setQty(qty);
					msgLogs.setMsgStatus("成功");
				}else{
					msgLogs.setQty(1);
					msgLogs.setMsgStatus("失败");
					msgLogs.setRemark((String)Dict.getAlias("SMS_CODE", status));
				}
				if("SMS".equals(msgLogs.getMsgType()) && msgLogs.getQty()>0){
					company.setSmsQty(company.getSmsQty() - msgLogs.getQty());
					dao.merge(company);
				}
			}
			edit(msgLogs);
		}
	}*/
	
	
	
	

	public List<SysAttach> uploadFile(MultipartFile[] multiFiles, SysAttach tpl){
		List<SysAttach> list=new ArrayList<SysAttach>();
		if(multiFiles!=null){
			for (int i = 0; i < multiFiles.length; i++) {
				if(multiFiles[i].getSize()>0){
					SysAttach attach =uploadFile(multiFiles[i]);
					attach.setAttachType(tpl.getAttachType());
					attach.setEntityType(tpl.getEntityType());
					attach.setEntityId(tpl.getEntityId());
					list.add(attach);
				}
			}
		}
		return list;
	}
	
	

	public SysAttach uploadFile(MultipartFile multiFile){
		SysAttach att = new SysAttach();
		String filePath =  "C:/upload/file";
		filePath = "/alidata/www/upload/upload/file";
		String urlPath="/upload/file";
		if(StringUtils.getNowTimes("yyyyMMdd").equals(TODAY)){
			TODAY_CNT = TODAY_CNT+1;
		}else{
			TODAY = StringUtils.getNowTimes("yyyyMMdd");
			TODAY_CNT = 0;
		}
		Timestamp now = new Timestamp(System.currentTimeMillis());
			if (multiFile != null && multiFile.getSize()!=0) {
				String fileName = multiFile.getOriginalFilename();
				fileName =  System.currentTimeMillis() +fileName.trim();
				int lastIndexOf = fileName.lastIndexOf(".");
				String suff = fileName.substring(lastIndexOf,fileName.length());
				if (!StringUtils.isEmpty(fileName.trim())) {
					String basePath= "/" + TODAY + "/" + TODAY_CNT+"-"+System.currentTimeMillis()+suff;
					// 重命名上传后的文件名
					String path = filePath + basePath;
					File localFile = new File(path);
					if (!localFile.exists()) {
						localFile.mkdirs();
					}
					try {
						multiFile.transferTo(localFile);
					} catch (IllegalStateException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
					String url = urlPath + basePath;
					// 新程序用这个
					att.setFilePath(url);
					att.setFileName(multiFile.getOriginalFilename());
					att.setCreateDate(now);
				}
			}
		return att;
	}
	
}
